package com.share.util.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.share.user.Gitee.GiteeUserInfo;
import com.share.user.Gitee.ProviderToken;
import com.share.user.weChat.dtos.TokenInfo;
import com.share.user.weChat.dtos.WxUserInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Http工具类
 */
@Slf4j
public final class HttpClientUtils {

    static final int TIMEOUT_MSPEC = 5 * 1000;

    private static final OkHttpClient client = new OkHttpClient();

    // 通用请求方法
    public static <T> T executeGetRequest(String url, Class<T> clazz,Object data) throws IOException {
        Request request = null;
        if(Objects.isNull(data)){
             request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();
        }else {
            MediaType mediaType = MediaType.get("application/json; charset=utf-8");
            RequestBody body = RequestBody.create(JSON.toJSONString(data), mediaType);
            request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();
        }
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("请求失败，状态码: " + response.code());
            }
            String responseBody = Objects.requireNonNull(response.body()).string();
            return JSON.parseObject(responseBody, clazz);
        }
    }




    /**
     * 通过code码获取用户的个人信息
     *
     * @param code      微信返回状态码
     * @param appID     appID
     * @param appSecret 标识
     * @return TokenInfo 对象
     * @throws IOException 如果请求失败
     */
    public static TokenInfo getTokenInfo(String code, String appID, String appSecret) throws IOException {
        OkHttpClient client = new OkHttpClient();

        String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" + appID +
                "&secret=" + appSecret +
                "&code=" + code +
                "&grant_type=authorization_code";

        Request request = new Request.Builder()
                .url(tokenUrl)
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }

            String responseBody = response.body().string();
            return JSONObject.parseObject(responseBody, TokenInfo.class);
        }
    }

    /**
     * 根据access_token获取用户信息
     *
     * @param tokenInfo 包含accessToken和openId的对象
     * @return WxUserInfo 对象
     * @throws IOException 如果请求失败
     */
    public static WxUserInfo getUserInfo(TokenInfo tokenInfo) throws IOException {
        OkHttpClient client = new OkHttpClient();

        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" + tokenInfo.getAccessToken() +
                "&openid=" + tokenInfo.getOpenId() +
                "&lang=zh_CN";

        Request request = new Request.Builder()
                .url(userInfoUrl)
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }

            String responseBody = response.body().string();
            return JSONObject.parseObject(responseBody, WxUserInfo.class);
        }
    }





    /**
     * 根据用户授权信息获取当前用户的 accessToken
     * 对用户进行授权，先创建一个GET请求，请求gitee中对应用户的访问令牌
     * @param providerToken 用户授权信息
     * @return 当前用户的 accessToken
     */
    public static String getGiteeTokenOkHttp(ProviderToken providerToken) {
        //1. 创建http请求，构建请求体和请求url等，并向gitee发起请求
        MediaType mediaType = MediaType.get("application/json; charset=utf-8");
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(JSON.toJSONString(providerToken), mediaType);
        String url = "https://gitee.com/oauth/token?grant_type=authorization_code&code=" +
                providerToken.getCode()
                + "&client_id=" + providerToken.getClientId()
                + "&redirect_uri=" + providerToken.getRedirectUri()
                + "&client_secret=" + providerToken.getClientSecret();
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        //2. 获取gitee对应的响应消息，根据消息解析出用户的 access token
        try (Response response = client.newCall(request).execute()) {
            String tokenStr = Objects.requireNonNull(response.body()).string();
            String accessToken = tokenStr.split(",")[0].split(":")[1];
            accessToken = accessToken.substring(1, accessToken.length() - 1);
            return accessToken;
        } catch (Exception e) {
            e.getStackTrace();
        }
        return null;
    }




    /**
     * 根据用户的 access token 获取当前gitee用户的详细信息
     * @param accessToken 用户的访问令牌
     * @return gitee用户对象
     */
    public static GiteeUserInfo getGiteeUserOkHttp(String accessToken) {
        //1. 构建http的GET请求，向gitee请求用户数据
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://gitee.com/api/v5/user?access_token=" + accessToken).build();

        //2. 获取gitee传回来的响应消息，根据消息解析出用户消息
        try {
            Response response = client.newCall(request).execute();
            String giteeUserStr = Objects.requireNonNull(response.body()).string();
            return JSON.parseObject(giteeUserStr, GiteeUserInfo.class);
        } catch (Exception e) {
            e.getStackTrace();
        }
        return null;
    }






    /**
     * 通过code码获取用户的个人信息
     *
     * @param code      微信返回状态码
     * @param appID     appID
     * @param appSecret 标识
     */
    @SneakyThrows
    public static TokenInfo getTokenInfoHttpClient(String code, String appID, String appSecret) throws IOException {
        //构建HTTP请求客户端
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            //用code交换token
            String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                    "appid=" + appID +
                    "&secret=" + appSecret +
                    "&code=" + code +
                    "&grant_type=authorization_code";
            //发请求
            HttpGet httpGet = new HttpGet(tokenUrl);
            String TokenInfoResult = "";
            //接受返回数据，转成utf-8的格式
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                TokenInfoResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
            //将结果封装到TokenInfo对象中
            return JSONObject.parseObject(TokenInfoResult, TokenInfo.class);
        } finally {
            httpClient.close();
        }

    }

    /**
     * 根据access_token获取用户信息
     */
    @SneakyThrows
    public static WxUserInfo getUserInfoHttpClient(TokenInfo tokenInfo) throws IOException {
        //构建HTTP请求客户端
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String UserInfoResult = null;
        try {
            //用accessToken获取扫码人的个人信息
            String UserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?" +
                    "access_token=" + tokenInfo.getAccessToken() +
                    "&openid=" + tokenInfo.getOpenId() +
                    "&lang=zh_CN";
            //构造http请求客户端
            HttpGet httpGet = new HttpGet(UserInfoUrl);
            //接受数据
            UserInfoResult = "";
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                UserInfoResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
            return JSONObject.parseObject(UserInfoResult, WxUserInfo.class);
        }finally {
            httpClient.close();
        }
    }










    /**
     * 根据用户授权信息获取当前用户的 accessToken
     * 对用户进行授权，先创建一个GET请求，请求gitee中对应用户的访问令牌
     * @param providerToken 用户授权信息
     * @return 当前用户的 accessToken
     */
    @SneakyThrows
    public static String getGiteeTokenHttpClient(ProviderToken providerToken){
        //1. 创建http请求，构建请求体和请求url等，并向gitee发起请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String TokenInfoResult = null;
        try {
            String GiteeTokenUrl = "https://gitee.com/oauth/token?grant_type=authorization_code&code=" + providerToken.getCode()
                    + "&client_id=" + providerToken.getClientId()
                    + "&redirect_uri=" + providerToken.getRedirectUri()
                    + "&client_secret=" + providerToken.getClientSecret();
            //发请求
            HttpGet httpGet = new HttpGet(GiteeTokenUrl);
            TokenInfoResult = "";
            //接受返回数据，转成utf-8的格式
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                log.info(response.getEntity().toString());
                TokenInfoResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
        } finally {
            httpClient.close();
        }
        //将结果封装到TokenInfo对象中
        return TokenInfoResult;
}



/**
 * 根据用户的 access token 获取当前gitee用户的详细信息
 *
 * @param accessToken 用户的访问令牌
 * @return gitee用户对象
 */
@SneakyThrows
public static GiteeUserInfo getGiteeUserHttpClient(String accessToken) {
    //1. 构建http的GET请求，向gitee请求用户数据
    CloseableHttpClient httpClient = HttpClients.createDefault();
    String UserInfoUrl = "https://gitee.com/api/v5/user?access_token=" + accessToken;

    //2. 获取gitee传回来的响应消息，根据消息解析出用户消息
    //构造http请求客户端
    HttpGet httpGet = new HttpGet(UserInfoUrl);
    //接受数据
   String GiteeUserInfoResult = "";
    HttpResponse response = httpClient.execute(httpGet);
    if (response.getStatusLine().getStatusCode() == 200) {
        GiteeUserInfoResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
    }
    return JSONObject.parseObject(GiteeUserInfoResult, GiteeUserInfo.class);
}




/**
 * 发送GET方式请求获取微信登录
 */
public static String doGet(String url, Map<String, String> paramMap) {
    // 创建Httpclient对象
    CloseableHttpClient httpClient = HttpClients.createDefault();

    String result = "";
    CloseableHttpResponse response = null;

    try {
        URIBuilder builder = new URIBuilder(url);
        if (paramMap != null) {
            for (String key : paramMap.keySet()) {
                builder.addParameter(key, paramMap.get(key));
            }
        }
        URI uri = builder.build();

        //创建GET请求
        HttpGet httpGet = new HttpGet(uri);

        //发送请求
        response = httpClient.execute(httpGet);

        //判断响应状态
        if (response.getStatusLine().getStatusCode() == 200) {
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            response.close();
            httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return result;
}

/**
 * 发送POST方式请求
 *
 * @param url
 * @param paramMap
 * @return
 * @throws IOException
 */
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
    // 创建Httpclient对象
    CloseableHttpClient httpClient = HttpClients.createDefault();
    CloseableHttpResponse response = null;
    String resultString = "";

    try {
        // 创建Http Post请求
        HttpPost httpPost = new HttpPost(url);

        // 创建参数列表
        if (paramMap != null) {
            List<NameValuePair> paramList = new ArrayList();
            for (Map.Entry<String, String> param : paramMap.entrySet()) {
                paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
            }
            // 模拟表单
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
            httpPost.setEntity(entity);
        }

        httpPost.setConfig(builderRequestConfig());

        // 执行http请求
        response = httpClient.execute(httpPost);

        resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return resultString;
}

/**
 * 发送POST方式请求
 *
 * @param url
 * @param paramMap
 * @return
 * @throws IOException
 */
public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
    // 创建Httpclient对象
    CloseableHttpClient httpClient = HttpClients.createDefault();
    CloseableHttpResponse response = null;
    String resultString = "";

    try {
        // 创建Http Post请求
        HttpPost httpPost = new HttpPost(url);

        if (paramMap != null) {
            //构造json格式数据
            JSONObject jsonObject = new JSONObject();
            for (Map.Entry<String, String> param : paramMap.entrySet()) {
                jsonObject.put(param.getKey(), param.getValue());
            }
            StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
            //设置请求编码
            entity.setContentEncoding("utf-8");
            //设置数据类型
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
        }

        httpPost.setConfig(builderRequestConfig());

        // 执行http请求
        response = httpClient.execute(httpPost);

        resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return resultString;
}

private static RequestConfig builderRequestConfig() {
    return RequestConfig.custom()
            .setConnectTimeout(TIMEOUT_MSPEC)
            .setConnectionRequestTimeout(TIMEOUT_MSPEC)
            .setSocketTimeout(TIMEOUT_MSPEC).build();
}



}
